package dao

import (
	"collection_srv/model"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/xuri/excelize/v2"
)

// ExcelConverter Excel转换器
type ExcelConverter struct {
	report *model.HealthReport
}

// NewExcelConverter 创建新的Excel转换器
func NewExcelConverter(report *model.HealthReport) *ExcelConverter {
	return &ExcelConverter{report: report}
}

// ConvertToExcel 将健康报告转换为Excel文件
func (ec *ExcelConverter) ConvertToExcel(outputDir string) (string, error) {
	// 1. 确保目录存在
	if err := ensureDirExists(outputDir); err != nil {
		return "", fmt.Errorf("创建目录失败: %w", err)
	}

	// 2. 生成Excel文件名
	filename := fmt.Sprintf("health_report_%d_%d.xlsx", ec.report.UserID, time.Now().Unix())
	filePath := filepath.Join(outputDir, filename)

	// 3. 创建Excel文件
	f := excelize.NewFile()
	sheetName := "健康报告"
	f.SetSheetName("Sheet1", sheetName)

	// 4. 写入数据
	row := 1
	ec.writeStats(f, sheetName, &row)
	if err := ec.writeAdvice(f, sheetName, &row); err != nil {
		return "", err
	}
	if err := ec.writeRecords(f, sheetName, &row); err != nil {
		return "", err
	}

	// 5. 设置样式
	if err := ec.setExcelStyle(f, sheetName, row); err != nil {
		return "", fmt.Errorf("设置Excel样式失败: %w", err)
	}

	// 6. 保存文件
	if err := f.SaveAs(filePath); err != nil {
		return "", fmt.Errorf("保存Excel文件失败: %w", err)
	}

	return filePath, nil
}

// ensureDirExists 确保目录存在
func ensureDirExists(dir string) error {
	return os.MkdirAll(dir, 0755)
}

// writeStats 写入统计信息
func (ec *ExcelConverter) writeStats(f *excelize.File, sheetName string, row *int) {
	statsData := []struct {
		title string
		value interface{}
	}{
		{"用户ID", ec.report.UserID},
		{"记录总数", ec.report.RecordCount},
		{"最早测量时间", ec.report.TimeRange.Earliest},
		{"最晚测量时间", ec.report.TimeRange.Latest},
		{"最高体温(°C)", fmt.Sprintf("%.1f", ec.report.Temperature.Max)},
		{"最低体温(°C)", fmt.Sprintf("%.1f", ec.report.Temperature.Min)},
		{"平均体温(°C)", fmt.Sprintf("%.1f", ec.report.Temperature.Avg)},
		{"体温趋势", ec.report.Temperature.Trend},
	}

	for _, data := range statsData {
		f.SetCellValue(sheetName, fmt.Sprintf("A%d", *row), data.title)
		f.SetCellValue(sheetName, fmt.Sprintf("B%d", *row), data.value)
		*row++
	}
	*row++ // 空一行
}

// writeAdvice 写入健康建议
func (ec *ExcelConverter) writeAdvice(f *excelize.File, sheetName string, row *int) error {
	if len(ec.report.HealthAdvice) == 0 {
		return nil
	}

	f.SetCellValue(sheetName, fmt.Sprintf("A%d", *row), "健康建议")
	f.SetCellStyle(sheetName, fmt.Sprintf("A%d", *row), fmt.Sprintf("A%d", *row), ec.getHeaderStyle(f))

	// 合并单元格
	mergeRange := fmt.Sprintf("A%d:B%d", *row+1, *row+len(ec.report.HealthAdvice))
	if err := f.MergeCell(sheetName, mergeRange, ""); err != nil {
		return fmt.Errorf("合并单元格失败: %w", err)
	}

	// 写入建议内容
	for i, item := range ec.report.HealthAdvice {
		f.SetCellValue(sheetName, fmt.Sprintf("A%d", *row+1+i), item)
	}

	// 设置自动换行样式
	style, _ := f.NewStyle(&excelize.Style{
		Alignment: &excelize.Alignment{WrapText: true},
	})
	f.SetCellStyle(sheetName, fmt.Sprintf("A%d", *row+1), fmt.Sprintf("B%d", *row+len(ec.report.HealthAdvice)), style)

	*row += len(ec.report.HealthAdvice) + 2 // 内容行数 + 标题行 + 空一行
	return nil
}

// writeRecords 写入详细记录
func (ec *ExcelConverter) writeRecords(f *excelize.File, sheetName string, row *int) error {
	if len(ec.report.DetailedRecords) == 0 {
		return nil
	}

	// 表头
	headers := []string{"记录ID", "设备ID", "采集时间", "体温(°C)", "状态"}
	for colIdx, header := range headers {
		col := string(rune('A' + colIdx))
		f.SetCellValue(sheetName, fmt.Sprintf("%s%d", col, *row), header)
		f.SetCellStyle(sheetName, fmt.Sprintf("%s%d", col, *row), fmt.Sprintf("%s%d", col, *row), ec.getHeaderStyle(f))
	}
	*row++

	// 内容行
	for _, rec := range ec.report.DetailedRecords {
		f.SetCellValue(sheetName, fmt.Sprintf("A%d", *row), rec.RecordID)
		f.SetCellValue(sheetName, fmt.Sprintf("B%d", *row), rec.DeviceID)
		f.SetCellValue(sheetName, fmt.Sprintf("C%d", *row), rec.CollectionTime)
		f.SetCellValue(sheetName, fmt.Sprintf("D%d", *row), fmt.Sprintf("%.1f", rec.Temperature))
		f.SetCellValue(sheetName, fmt.Sprintf("E%d", *row), rec.Status)
		*row++
	}

	return nil
}

// setExcelStyle 设置Excel样式
func (ec *ExcelConverter) setExcelStyle(f *excelize.File, sheetName string, lastRow int) error {
	// 设置列宽
	f.SetColWidth(sheetName, "A", "A", 15)
	f.SetColWidth(sheetName, "B", "B", 15)
	f.SetColWidth(sheetName, "C", "C", 20)
	f.SetColWidth(sheetName, "D", "D", 15)
	f.SetColWidth(sheetName, "E", "E", 15)

	// 设置详细记录的边框
	style, _ := f.NewStyle(&excelize.Style{
		Border: []excelize.Border{
			{Type: "left", Color: "000000", Style: 1},
			{Type: "top", Color: "000000", Style: 1},
			{Type: "right", Color: "000000", Style: 1},
			{Type: "bottom", Color: "000000", Style: 1},
		},
	})
	// 假设详细记录从第12行开始（根据实际数据调整）
	if lastRow > 12 {
		f.SetCellStyle(sheetName, "A12", fmt.Sprintf("E%d", lastRow-1), style)
	}
	return nil
}

// getHeaderStyle 获取表头样式
func (ec *ExcelConverter) getHeaderStyle(f *excelize.File) int {
	style, _ := f.NewStyle(&excelize.Style{
		Font:      &excelize.Font{Bold: true},
		Alignment: &excelize.Alignment{Horizontal: "center"},
		Fill:      excelize.Fill{Type: "pattern", Color: []string{"#DDEBF7"}, Pattern: 1},
	})
	return style
}
